<template>
  <el-popover
    placement="bottom"
    width="100%"
    :disabled="disabled || readonly"
    trigger="click"
    :value="visible"
    popper-class="c-org-select-popper"
    class="c-org-select-vertical"
  >
    <el-input
      slot="reference"
      readonly
      :disabled="disabled"
      :placeholder="placeholder"
      :value="innerLabel"
      class="ipt"
    >
      <i
        v-if="clearable"
        v-show="!!value"
        slot="suffix"
        class="el-icon-error clearable"
        @click.stop="clearValue"
      />
    </el-input>
    <el-input
      v-if="showSearch"
      v-model.trim="searchKey"
      size="small"
      placeholder=""
      @keyup.native.enter="handleSearch"
    >
      <el-button slot="append" icon="el-icon-search" @click="handleSearch" />
    </el-input>
    <el-tree
      ref="tree"
      v-loading="isLoading"
      :data="treeData"
      node-key="id"
      lazy
      :load="loadChild"
      :props="{ label: 'name' }"
      :default-expand-all="false"
      :draggable="false"
      :expand-on-click-node="false"
      highlight-current
      :current-node-key="innerValue"
      :filter-node-method="filterTree"
      class="tree"
      @current-change="change"
    />
  </el-popover>
</template>

<script>
import { nativeWin } from '@/utils'
import api from '@/api/index'
export default {
  props: {
    value: String,
    label: String,
    clearable: {
      type: Boolean,
      default: false
    },
    addRoot: {
      type: Boolean,
      default: false
    },
    showSearch: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: ''
    },
    disabledKeys: {
      type: Array,
      default: () => []
    },
    disabled: Boolean,
    readonly: Boolean
  },
  data () {
    return {
      searchKey: '',
      loadTree: true,
      isLoading: false,
      treeData: [],
      visible: false
    }
  },
  computed: {
    innerLabel: {
      get () {
        return this.label
      },
      set (v) {
        this.$emit('update:label', v)
      }
    },
    innerValue: {
      get () {
        return this.value
      },
      set (v) {
        this.$emit('update:value', v)
      }
    }
  },
  created () {
    this.loadParent()
  },
  methods: {
    clearValue () {
      this.change(null, null, true)
    },
    async loadChild (node, resolve) {
      const code = node?.data?.code || null
      if(!code) {
        resolve()
      }
      const data = await this.getData({parentCode: code})
      resolve(node.level < 12 ? data : [])
    },
    handleSearch () {
      this.$refs.tree.filter()
    },
    async loadParent () {
      this.isLoading = true
      const ret = this.addRoot
        ? [
            {
              name: '根目录',
              id: '',
              children: ret
            }
          ]
        : []
      const res = await this.getData({ level: 1, parentCode: null }).finally(
        () => {
          this.isLoading = false
        }
      ) ?? []
      this.treeData = [...ret, ...res]
    },
    getData (param) {
      return new Promise((resolve, reject) => {
        api
          .organization(param)
          .then(res => {
            const ret = res?._embedded?.organizations.map(itm => ({
              id: itm.id,
              name: itm.shortName,
              code: itm.code
            }))
            resolve(ret)
          })
          .catch(() => {
            reject([])
          })
      })
    },
    handleDisabledNode (arr) {
      if (!this.disabledKeys) {
        return arr
      }
      arr && arr.length &&
        arr.forEach((itm, index) => {
          if (itm.id && this.disabledKeys.includes(itm.id)) {
            arr.splice(index, 1)
          }
          itm.children && (itm.children = this.handleDisabledNode(itm.children))
        })
      return arr
    },
    filterTree (_, data) {
      return (
        !this.searchKey ||
        (data.name || '').toLowerCase().includes(this.searchKey.toLowerCase())
      )
    },
    change (data, _, isNotUserTrigger) {
      this.innerValue = data?.id
      this.innerLabel = data?.name
      if (!isNotUserTrigger) {
        nativeWin.document.body.click()
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.c-org-select-vertical {
  ::v-deep .el-popover__reference {
    .clearable {
      cursor: pointer;
      opacity: 0;
    }
    &:hover {
      .clearable {
        opacity: 1;
      }
    }
  }
}
</style>

<style lang="scss">
div.c-org-select-popper {
  min-width: 200px;
  .tree {
    max-height: 400px;
    overflow: auto;
  }
}
</style>
